import { Form, Input, Button, DatePicker,  } from "antd";
import { BaseModel } from "./service/base.service";
import { Component } from "react";
import React from 'react';
import { FormComponentProps } from "antd/lib/form";
import TextArea from "antd/lib/input/TextArea";
import { Moment } from "moment";
import moment from "moment";
import BraftEditor from 'braft-editor';
import 'braft-editor/dist/index.css'
export interface IFormItemProps {
    title: string;
    placeholder: string;
    type: FormItemType;
    values: (number | string | Date | Moment) | (number | string | Date | Moment)[];
    key: string;
}

export interface IFormHelperMap { 
    [index: string]: IFormItemProps;
}

export function formItemType(title: string, type?: FormItemType, placeholder?: string, values?: any[]) { 
    return function (target: any, propertyKey: string) { 
        let key = "__form_helper"
        Object.defineProperty(target, key, {
            enumerable: false,
            value: target[key] || {} as IFormHelperMap,
        });

        target.__form_helper[propertyKey] = {
            key: propertyKey,
            type,
            title,
            placeholder: placeholder || title,
            values,
        } as IFormItemProps;
    }
}

export interface FormHelperProps { 
    model: BaseModel,
    onSubmit?: IOnSubmitHandler;
}

export enum FormItemType { 
    ID,
    TEXT,
    NUMBER,
    DATE,
    PASSWORD,
    TEXTAREA,
    HIDDEN,
    EDITOR,
}

export interface IOnSubmitHandler { 
    (formFieldValues: {[index: string]: any}): void;
}
export class FormHelper extends Component<FormHelperProps & FormComponentProps> { 
    static create(model: BaseModel, name: string, onSubmitHandler?: IOnSubmitHandler) { 
        const CmsForm = Form.create({ name: name })(FormHelper);
        return <CmsForm model={model} onSubmit={onSubmitHandler}></CmsForm>
    }
    handleSubmit = (e: any) => {
        this.props.form.validateFields((err) => {
            e.preventDefault();
            if (err) { 
                return;
            }
            if (this.props.onSubmit && typeof this.props.onSubmit == 'function') {
                this.props.onSubmit(this.props.form.getFieldsValue());
            } else {
                console.warn('props not has onSubmit function, form values is ', this.props.form.getFieldsValue(), 'ignore!');
            }
        });
    }
    componentDidMount() {
        this.props.form.setFieldsValue(this.props.model);
    }
    private formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 8 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 16 },
        },
    };
    getFormItem(props: IFormItemProps) {
        const { getFieldDecorator, setFieldsValue } = this.props.form;
        let formItem;
        let values = props.values;
        switch (props.type) { 
            case FormItemType.ID:
                formItem = <Input type="text" readOnly={true}></Input>
                break;
            case FormItemType.TEXTAREA:
                formItem = <TextArea rows={5} placeholder={props.placeholder}></TextArea>
                break;
            case FormItemType.DATE:
                // let dateValue = props.values;
                if (!values) { 
                    values = moment();
                }
                if (typeof values == 'string' || typeof values == 'number') { 
                    values = moment(values);
                }
                formItem = <div><DatePicker
                    showTime
                    placeholder="Select Time"
                    value={values as Moment}
                    onOk={(value) => setFieldsValue({ [props.key]: value && value.toDate()})}
                /><Input type="hidden" placeholder={props.placeholder}></Input></div>
                break;
            case FormItemType.NUMBER:
                formItem = <Input type="number" placeholder={props.placeholder}></Input>
                break;
            case FormItemType.EDITOR:
                values = BraftEditor.createEditorState(values);
                //onChange={(value) => { setFieldsValue({ [props.key]: value.toHTML() }) }}
                formItem = <div style={{ border: '1px solid #d9d9d9' }}>
                    <BraftEditor  value={values}></BraftEditor>
                    <Input type="hidden" placeholder={props.placeholder} /></div>
                break;
            case FormItemType.PASSWORD:
                formItem = <Input type="password" placeholder={props.placeholder}></Input>
                break;
            case FormItemType.HIDDEN:
                formItem = <Input type="hidden" placeholder={props.placeholder}></Input>
                break;
            default:
                formItem = <Input placeholder={props.placeholder}></Input>;
        }
        return (
            <Form.Item key={props.key} label={props.title} {...this.formItemLayout}>
                {getFieldDecorator(props.key, {
                    rules: [{ required: true, message: `${props.title}不能为空` }],
                    initialValue: values,
                })(
                    formItem
                )}
            </Form.Item>
        )
    }

    render() {
        let items = [];
        let formItemMap = (this.props.model as any).__form_helper as IFormHelperMap || {};
        for (let key in this.props.model) { 
            let metedata = formItemMap[key];
            if (!metedata) { 
                metedata = {
                    key: key,
                    title: key,
                    type: FormItemType.TEXT,
                    placeholder: key,
                    values: (this.props.model as any)[key],
                }
            }
            metedata.values = (this.props.model as any)[key];
            items.push(this.getFormItem(metedata));
        }
        return (
            <Form onSubmit={this.handleSubmit.bind(this)}>
                {items}
                <Form.Item {...this.formItemLayout}>
                 <Button type="primary" htmlType="submit" className="login-form-button">提交</Button>
                </Form.Item>
            </Form>
        )
    }
}